import classNames from "classnames";
import React, { useState, useContext, ReactNode } from "react";
import { createUseStyles } from "react-jss";
import type { BlockProps } from "./type";

export default Block;

const isFr = (v: any) => v === "fr" || v === "fraction";

export const addPx = (v: any) => {
  if (!isNaN(v as unknown as number)) return v + "px";
  // 当宽高标记为 fraction 时，设置一个固定默认大小，然后配合 flex-grow 实现均匀分布
  if (isFr(v)) return "50px";
  return v;
};

export const creatStyleBlock = ({
  horizontal,
  width,
  height,
  gutter,
  noGap,
  grow,
  shrink,
}: Omit<BlockProps, "children"> & { noGap: boolean }) => {
  const autoFlex = isFr(width) || isFr(height);
  const flexGrow = grow != undefined ? grow : autoFlex ? 1 : 0;
  const flexShrink = shrink != undefined ? shrink : autoFlex ? 1 : 0;
  return {
    display: "flex",
    overflow: width || height ? "auto" : "unset",
    flexDirection: horizontal ? "row" : "column",
    width: addPx(width),
    height: addPx(height),
    flexGrow,
    flexShrink,
    padding: noGap ? 0 : `${gutter![0] / 2}px ${gutter![1] / 2}px`,
  };
};

export const getNoGapValue = (
  isRootBlock: boolean | undefined,
  firstChild: ReactNode
) => {
  return Boolean(
    !isRootBlock &&
      firstChild &&
      typeof firstChild == "object" &&
      "type" in firstChild &&
      typeof firstChild.type != "string" &&
      firstChild.type.name == Block.name
  );
};

const BlockContext = React.createContext<{
  gutter: [number, number];
  isRootBlock?: boolean;
}>({ gutter: [0, 0], isRootBlock: true });

const useStyles = createUseStyles<
  string,
  Omit<BlockProps, "children"> & { noGap: boolean }
>({
  block: (props) => {
    return creatStyleBlock({ ...props });
  },
});

function Block({
  gutter,
  width,
  height,
  horizontal,
  className,
  children,
  grow,
  shrink,
}: BlockProps) {
  const context = useContext(BlockContext);

  const currentGutter = context.isRootBlock
    ? gutter || [16, 16]
    : gutter || context.gutter;

  const [value] = useState({ gutter: currentGutter });

  const firstChild = Array.isArray(children) ? children[0] : children;

  const classes = useStyles({
    gutter: currentGutter,
    grow,
    shrink,
    width,
    height,
    horizontal,
    noGap: getNoGapValue(context.isRootBlock, firstChild),
  });
  return (
    <BlockContext.Provider value={value}>
      <div className={classNames("ct0-block", classes.block, className)}>
        {children}
      </div>
    </BlockContext.Provider>
  );
}
